/**
 * @file value.h
 * @brief VimL虚拟机的值类型系统
 * @author VimLVM Team
 * @date 2025
 */

#ifndef VIML_VALUE_H
#define VIML_VALUE_H

#include "common.h"
#include "instruction.h"
#include "debug_info.h"  // 调试信息支持
#include <string>
#include <vector>
#include <unordered_map>
#include <variant>

namespace viml {

// 值类型枚举
enum class ValueType {
    NIL,
    BOOLEAN,
    NUMBER,
    STRING,
    LIST,
    DICT,
    FUNCTION,
    CLOSURE
};

// 前向声明
struct List;
struct Dict;
struct Function;
struct Closure;

// 使用variant实现动态类型
using ValueData = std::variant<
    std::monostate,    // NIL
    bool,              // BOOLEAN
    double,            // NUMBER
    std::string,       // STRING
    std::shared_ptr<List>,    // LIST
    std::shared_ptr<Dict>,    // DICT
    std::shared_ptr<Function>, // FUNCTION
    std::shared_ptr<Closure>   // CLOSURE
>;

struct List {
    std::vector<std::shared_ptr<Value>> elements;
    
    List() = default;
    explicit List(size_t size) : elements(size) {}
};

struct Dict {
    std::unordered_map<std::string, std::shared_ptr<class Value>> elements;
};

struct Function {
    std::string name;
    std::vector<std::string> parameters;
    std::vector<Instruction> bytecode;
    std::vector<Value> constants;  // 常量池
    size_t locals_count;
    std::shared_ptr<DebugInfo> debug_info;  // 调试信息
    
    Function(std::string n = "", std::vector<std::string> params = {}, 
             std::vector<Instruction> code = {}, size_t locals = 0)
        : name(std::move(n)), parameters(std::move(params)), 
          bytecode(std::move(code)), locals_count(locals), 
          debug_info(std::make_shared<DebugInfo>()) {}
};

struct Closure {
    std::shared_ptr<Function> function;
    std::vector<Value> captures;
    
    Closure(std::shared_ptr<Function> func, std::vector<Value> caps)
        : function(std::move(func)), captures(std::move(caps)) {}
};

class Value {
public:
    Value() : data_(std::monostate{}) {}
    explicit Value(bool b) : data_(b) {}
    explicit Value(double n) : data_(n) {}
    explicit Value(const char* s) : data_(std::string(s)) {}
    explicit Value(std::string s) : data_(std::move(s)) {}
    explicit Value(std::shared_ptr<List> l) : data_(std::move(l)) {}
    explicit Value(std::shared_ptr<Dict> d) : data_(std::move(d)) {}
    explicit Value(std::shared_ptr<Function> f) : data_(std::move(f)) {}
    explicit Value(std::shared_ptr<Closure> c) : data_(std::move(c)) {}

    ValueType type() const;
    bool is_nil() const;
    bool is_boolean() const;
    bool is_number() const;
    bool is_string() const;
    bool is_list() const;
    bool is_dict() const;
    bool is_function() const;
    bool is_closure() const;

    bool as_boolean() const;
    double as_number() const;
    const std::string& as_string() const;
    const std::shared_ptr<List>& as_list() const;
    const std::shared_ptr<Dict>& as_dict() const;
    const std::shared_ptr<Function>& as_function() const;
    const std::shared_ptr<Closure>& as_closure() const;

    std::string to_string() const;
    bool operator==(const Value& other) const;
    bool operator!=(const Value& other) const;

private:
    ValueData data_;
};

} // namespace viml

#endif // VIML_VALUE_H